Objetivos:¶

Construir um agente inteligente capaz de operar na bolsa de valores a partir de experimentos de compra e venda de ações. Dado um saldo inicial, o modelo deve apresentar o resultado (lucro) a ser obtido depois de ações de compra e venda.

Observação:¶

Esta análise de dados tem como único propósito a demonstração e teste da implementação básica de um agente inteligente. Não deve ser interpretada como um conselho de atuação no mercado de ações.

https://plotly.com/

In [1]:
!pip install -q plotly
In [2]:
#Imports
import random
import plotly.graph_objects as go
import pandas as pd
import numpy as np
from datetime import datetime

Carregando e Visualizando os Dados com Candlestick¶

In [3]:
df=pd.read_csv('dataset.csv')
In [6]:
df.shape
Out[6]:
(506, 11)
In [7]:
df.head()
Out[7]:
Date AAPL.Open AAPL.High AAPL.Low AAPL.Close AAPL.Volume AAPL.Adjusted dn mavg up direction
0 2015-02-17 127.489998 128.880005 126.919998 127.830002 63152400 122.905254 106.741052 117.927667 129.114281 Increasing
1 2015-02-18 127.629997 128.779999 127.449997 128.720001 44891700 123.760965 107.842423 118.940333 130.038244 Increasing
2 2015-02-19 128.479996 129.029999 128.330002 128.449997 37362400 123.501363 108.894245 119.889167 130.884089 Decreasing
3 2015-02-20 128.619995 129.500000 128.050003 129.500000 48948400 124.510914 109.785449 120.763500 131.741551 Increasing
4 2015-02-23 130.020004 133.000000 129.660004 133.000000 70974100 127.876074 110.372516 121.720167 133.067817 Increasing

Facilitando a visualização da variação dos preços por meio de um gráfico de vela.

In [10]:
#Candlestick
fig=go.Figure(data=[go.Candlestick(x=df['Date'],
                                  open=df['AAPL.Open'],
                                  high=df['AAPL.High'],
                                  low=df['AAPL.Low'],
                                  close=df['AAPL.Close'])])
fig.show()
In [11]:
#Trabalhando com a cotação de fechamento da ação da Apple
precos=df['AAPL.Close'].values
In [12]:
type(precos)
Out[12]:
numpy.ndarray

Configuração do Algoritmo Q-Learning¶

In [13]:
#Configuração do Q-Learning
print('\nDefinindo os Hiperparâmetros do Q-Learning')
num_episodios=1000
alfa=0.1
gama=0.99
epsilon=0.1
Definindo os Hiperparâmetros do Q-Learning

Configuração do Ambiente de Negociação¶

In [14]:
#Configuração do ambiente de negociação
print('\nConfigurando o Ambiente de Negociação')
acoes=['comprar','vender','manter']
saldo_inicial=1000
num_acoes_inicial=0
Configurando o Ambiente de Negociação

Função para Executar as Ações (Passos) do Robô Trading¶

In [15]:
#Função para executar uma ação e retornar a recompensa e o próximo estado
def executar_acao(estado, acao, saldo, num_acoes, preco):
    #Comprar
    if acao==0:
        if saldo>=preco:
            num_acoes+=1
            saldo-=preco
    #Vender
    elif acao==1:
        if num_acoes>0:
            num_acoes-=1
            saldo+=preco
    #Define o lucro
    lucro=saldo+num_acoes*preco-saldo_inicial
    
    return (saldo, num_acoes, lucro)

Treinamento do Robô¶

In [16]:
#Inicializar a tabela Q
print('\nInicializando a Tabela Q...')
q_tabela=np.zeros((len(precos), len(acoes)))
Inicializando a Tabela Q...
In [17]:
#Treinamento
print('\nInicializando o Treinamento...')
for _ in range(num_episodios):
    
    #Define o saldo
    saldo=saldo_inicial
    
    #Define o número de acoes
    num_acoes=num_acoes_inicial
    
    #Loop
    for i, preco in enumerate(precos[:-1]):
        estado=i
        #Escolher a ação usando a política epsilon-greedy
        if np.random.random()<epsilon:
            acao=random.choice(range(len(acoes)))
        else:
            acao=np.argmax(q_tabela[estado])
        
        #Executar a ação e obter a recompensa e o próximo estado
        saldo, num_acoes, lucro=executar_acao(estado, acao, saldo, num_acoes, preco)
        prox_estado=i+1
        
        #Atualizar a tabela Q
        q_tabela[estado][acao]+=alfa*(lucro+gama*np.max(q_tabela[prox_estado])-q_tabela[estado][acao])
        
print('\nTreinamento Concluído')    
Inicializando o Treinamento...

Treinamento Concluído

Executando o Robô Trading e Prevendo o Lucro de Operações na Bolsa de Valores¶

In [18]:
#Valores iniciais para testar o agente
saldo=saldo_inicial
num_acoes=num_acoes_inicial
In [19]:
print('\nExecutando o Agente...')
for i, preco in enumerate(precos[:-1]):
    estado=i
    acao=np.argmax(q_tabela[estado])
    saldo, num_acoes, _=executar_acao(estado, acao, saldo, num_acoes, preco)
print('\nExecução Concluída')
Executando o Agente...

Execução Concluída
In [20]:
num_acoes
Out[20]:
5
In [21]:
precos[-1]
Out[21]:
135.350006
In [22]:
#Vendendo todas as ações no último preço
saldo+=num_acoes*precos[-1]
lucro=saldo-saldo_inicial
lucro_final=round(lucro,2)
In [23]:
print(f"\nComeçamos a Negociação com saldo inicial de 1000 e tivemos lucro de: {lucro_final}")
Começamos a Negociação com saldo inicial de 1000 e tivemos lucro de: 73.22